<?php
	//User class
	class User {
		private $user_id;
		private $user_username;
		private $user_password;
		private $user_email;
		private $user_firstname;
		private $user_lastname;
		private $user_gender;
		private $user_address;
		private $user_contact;
		private $user_dob;
		private $user_role;
		private $user_time;
		private $user_valid;
		private $user_benchmark;
		private $user_salt;

		//Note: Constructor does not set ID however insert() and User::createUser() sets ID
		//      Use User::createUser() for manipulation of User
		
		//Constructor for User
		//
		//Param: username, password, email, firstname, lastname, 
		//		 gender, address, contact, date of birth, role, time
		function __construct($user_username, $user_password, $user_email, 
								$user_firstname, $user_lastname, $user_gender, 
								$user_address, $user_contact, 
								$user_dob, $user_role, $user_time) {

			$this->setUsername($user_username);
			if ($user_password !== null) {
				$this->setSalt();
				$this->setPassword($user_password);
			}
			$this->setEmail($user_email);
			
			$this->setFirstname($user_firstname);
			$this->setLastname($user_lastname);
			$this->setGender($user_gender);
			$this->setAddress($user_address);
			$this->setContact($user_contact);
			$this->setDoB($user_dob);
			$this->setRole($user_role);
			if ($user_time !== null) {
				$this->setTime($user_time);
			}
		}
		
		//Setter for Salt
		function setSalt() {
			$salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);
			$this->user_salt = $salt;
		}
		//Getter for Salt
		function getSalt() {
			return $this->user_salt;
		}	
		
		//Setter for User ID
		function setUserID($val) {
			$this->user_id = $val;
		}
		//Getter for User ID
		function getUserID() {
			return $this->user_id;
		}
		
		//Setter for Username
		function setUsername($val) {
			$this->user_username = $val;
		}
		//Getter for Username
		function getUsername() {
			return $this->user_username;
		}
		
		//Setter for Password
		function setPassword($val) {
			$password = $this->generateHash($val);
			$this->user_password = $password;
		}
		//Getter for Password
		function getPassword() {
			return $this->user_password;
		}
		
		//Setter for Email
		function setEmail($val) {
			$this->user_email = $val;
		}
		//Getter for Email
		function getEmail() {
			return $this->user_email;
		}
		
		//Setter for First Name
		function setFirstname($val) {
			$this->user_firstname = $val;
		}
		//Getter for First Name
		function getFirstname() {
			return $this->user_firstname;
		}
		
		//Setter for Last Name
		function setLastname($val) {
			$this->user_lastname = $val;
		}
		//Getter for Last Name
		function getLastname() {
			return $this->user_lastname;
		}

		//Setter for Gender
		function setGender($val) {
			$this->user_gender = $val;
		}
		//Getter for Gender
		function getGender() {
			return $this->user_gender;
		}
		
		//Setter for Address
		function setAddress($val) {
			$this->user_address = $val;
		}
		//Getter for Address
		function getAddress() {
			return $this->user_address;
		}
		
		//Setter for Contact
		function setContact($val) {
			$this->user_contact = $val;
		}
		//Getter for Contact
		function getContact() {
			return $this->user_contact;
		}
		
		//Setter for Date of Birth
		function setDoB($val) {
		    $time = strtotime( $val );
		    $date = date("Y-m-d", $time );
			$this->user_dob = $date;
		}
		//Getter for Date of Birth
		function getDoB() {
			return $this->user_dob;
		}
		
		//Setter for Role
		function setRole($val) {
			$this->user_role = $val;
		}
		//Getter for Role
		function getRole() {
			return $this->user_role;
		}	
		
		//Setter for Time
		function setTime($val = null) {
			if ($val === null) {	
				$this->user_time = date(DATE_FORMAT);
			} else {
				$this->user_time = $val;
			}
		}				
		//Getter for Time
		function getTime() {
			return $this->user_time;
		}

		//Setter for Valid
		function setValid($val) {
			$this->user_valid = $val;
		}
		//Getter for Valid
		function getValid() {
			return $this->user_valid;
		}			
		
		//Insert new User info into database
		//Sets User ID to current User object
		//
		//Return: User ID or 0
		function insert() {
			$this->setTime();
			$db = Database::get();
			$query = "INSERT INTO " . USER_TABLE . " 
				(user_username, user_password, user_email, 
				user_firstname, user_lastname, user_gender, 
				user_address, user_contact, user_dob, user_role, created_at, user_valid)
				VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {
				
				$user_username = $this->getUsername();
				$user_password = $this->getPassword();
				$user_email = $this->getEmail();
				

				$user_firstname = $this->getFirstname();
				$user_lastname = $this->getLastname();
				$user_gender = $this->getGender();
				
				//Encode starts here				
				$user_address = base64_encode($this->getAddress());
				$user_contact = base64_encode($this->getContact());
				$user_dob = base64_encode($this->getDoB());
				//Encode ends
				
				$user_role = $this->getRole();		
				$user_time = $this->getTime();
				
				//Random token
				$user_token = $this->generateValidationToken();
				
				$stmt->bind_param("ssssssssssss", $user_username, $user_password, $user_email, 
									$user_firstname, $user_lastname, $user_gender, 
									$user_address, $user_contact, $user_dob, $user_role, $user_time, $user_token);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$user_id = $stmt->insert_id;
				$this->setUserID($user_id);
				$this->setValid($user_token);
				$stmt->close();
				
				//Send validation email 
				$this->sendEmailToken(); 
				
				return intval($user_id);
			}
			return 0;
		}
	
		//Update the database with new values in the User object
		//
		//Return: true or false
		function update() {
			$db = Database::get();
			$query = "UPDATE " . USER_TABLE . " 
				SET user_firstname = ?, user_lastname = ?, user_gender = ?, 
				user_address = ?, user_contact = ?, user_dob = ? 
				WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {

				$user_firstname = $this->getFirstname();
				$user_lastname = $this->getLastname();
				$user_gender = $this->getGender();
				
				//Encode starts				
				$user_address = base64_encode($this->getAddress());
				$user_contact = base64_encode($this->getContact());
				$user_dob = base64_encode($this->getDoB());
				//Encode ends
				
				$user_id = $this->getUserID();
				
				$stmt->bind_param("ssssssd", $user_firstname, $user_lastname, $user_gender, 
									$user_address, $user_contact, $user_dob, $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
				
				return true;
			}
			
			return false;
		}		

		//Update password given the new password
		//
		//Return: true or false
		function updatePassword($password) {
			$db = Database::get();
			$query = "UPDATE " . USER_TABLE . " 
				SET user_password = ? WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				
				$salt = self::findSalt($user_id);
				$hash_password = $salt . sha1($salt . $password);
				
				$stmt->bind_param("sd", $hash_password, $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
				
				return true;
			}
			
			return false;
		}

		//Update email with the new e-mail
		//
		//Return: true or false
		function updateEmail($email) {
			$db = Database::get();
			$query = "UPDATE " . USER_TABLE . " 
				SET user_email = ? WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				$stmt->bind_param("sd", $email, $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
				
				return true;
			}
			
			return false;
		}
		
		//Get the new e-mail of the user
		//
		//Return: new e-mail
		function getNewEmail() {
			$db = Database::get();
			$email_new = null;
			$query = "SELECT email_new FROM " . USER_EMAIL_TABLE . "
					  WHERE user_id = ? AND email_token <> 0;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($email_new);
				$stmt->fetch() or $email_new = null;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return $email_new;
		}

		//Request e-mail change given the new e-mail
		//
		//Param: new e-mail
		//Return: true or false	
		function requestEmailChange($email_new) {
			$db = Database::get();
			$query = "INSERT INTO " . USER_EMAIL_TABLE . " 
				(user_id, email_old, email_new, email_token, requested_at)
				VALUES(?, ?, ?, ?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {				
				$user_id = $this->getUserID();
				$email_old = $this->getEmail();
				$token = substr(uniqid ($this->getUsername(), true), -5);
				$email_time = date(DATE_FORMAT);
				
				$stmt->bind_param("dssss", $user_id, $email_old, $email_new, $token, $email_time);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
				
				$this->sendEmailChangeToken($token);
				return true;
			}
			return false;	
		}

		//Check if the user has requested an e-mail change
		//
		//Return: true or false			
		function hasRequestEmailChange() {
			$db = Database::get();
			$id = 0;
			$query = "SELECT user_id FROM " . USER_EMAIL_TABLE . "
					  WHERE user_id = ? AND email_token <> 0;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if (intval($id) !== 0) {
				return true;
			}
			return false;	
		}

		//Remove a e-mail request change
		//
		//Return: true or false					
		function removeRequestEmailChange() {
			$db = Database::get();
			$query = "DELETE FROM " . USER_EMAIL_TABLE . " 
				WHERE user_id = ? AND email_token <> 0;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
				
				//Change token back to 'true'
				self::changeToken($user_id, 'true');
				
				return true;
			}
			return false;
		}

		//Update e-mail token given the e-mail token
		//
		//Param: e-mail token
		//Return: true or false			
		function updateEmailToken($token) {
			$db = Database::get();
			$query = "UPDATE " . USER_EMAIL_TABLE . " 
				SET email_token = ? WHERE user_id = ? AND email_token <> 0;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				$stmt->bind_param("sd", $token, $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();				
				return true;
			}
			return false;
		}

		//Confirm e-mail change given the username and token
		//If username and token are correct,
		//	Remove e-mail token, update the new e-mail and send re-validation to new e-mail
		//
		//Param: username, e-mail token
		//Return: true or false				
		static function confirmEmailChange($username, $token) {
			$db = Database::get();
			$id = 0;
			$query = "SELECT user_id FROM " . USER_EMAIL_TABLE . "
					  WHERE user_id = ? AND email_token = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = intval(self::findID($username));
				
				$stmt->bind_param("ds", $user_id, $token);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if (intval($id) !== 0) {
				$user = self::createUser($id);
				//Get new e-mail
				$email_new = $user->getNewEmail();
				//Remove the e-mail token
				$user->updateEmailToken(0);
				//Set the new e-mail
				$user->setEmail($email_new);
				//Update the new e-mail
				$user->updateEmail($email_new);
				
				//Random token
				$user_token = $user->generateValidationToken();
				$user->setValid($user_token);
				self::changeToken($user_id, $user_token);
				//Send re-validation to new e-mail
				$user->sendEmailNewToken();
				return true;
			}
			return false;			
		}

		//Attach Android id to user given the Android id
		//
		//Param: Android id
		//Return: true or false				
		function attachAndroidID($android_id) {
			$db = Database::get();
			$query = "INSERT INTO " . USER_ANDROID_TABLE . " 
				(user_id, android_id)
				VALUES(?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {				
				$user_id = $this->getUserID();
				
				$stmt->bind_param("ds", $user_id, $android_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
							
				return true;
			}
			return false;
		}

		//Get list of Android id given the user id
		//
		//Param: user id
		//Return: List of Android id		
		static function findAndroidID($user_id) {
			$android_list = null;
			$db = Database::get();
			$query = "SELECT android_id FROM " . USER_ANDROID_TABLE . "
					  WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$result = $stmt->get_result(); 
				
				while($row = $result->fetch_assoc()) {
					$android_list[] = $row['android_id'];
				} 
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return $android_list;
		}	

		//Remove Android id to user given the user id and Android id
		//
		//Param: user id, Android id
		//Return: true or false			
		static function removeAndroidID($user_id, $android_id) {
			$db = Database::get();
			$query = "DELETE FROM " . USER_ANDROID_TABLE . " 
				WHERE user_id = ? AND android_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("dd", $user_id, $android_id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();	
				return true;
			}		
			return false;
		}
		
		//Push Android notification to android device
		//Whenever a notification is created, it should be pushed to the android devices.
		//
		//Param: user id, notification id, notification time	
		static function pushAndroidNotification($push_id, $notification_id, $time){		
			// GCM			
			$url = 'https://android.googleapis.com/gcm/send';
			// from Google
			$serverApiKey = "AIzaSyB1CrXY1y8ciza-WAPCDUgjM4zdv6Q5XnQ";
			//$reg = "Array";
			$regArray = User::findAndroidID($push_id);
			
			$headers = array(
			 'Content-Type:application/json',
			 'Authorization:key=' . $serverApiKey
			 );

			$object = Notification::createNotification($notification_id);
			 
			$message = $object->getMessage();
			
			$data = array('registration_ids' => 
						$regArray, 'data' => 
							array('type' => 'New', 
								'title' => 'GCM', 
								'msg' => $message, 
								'time' => $time
							)
					);

			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			if ($headers)
			curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_POST, true);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

			$response = curl_exec($ch);

			curl_close($ch);
			//debuggin only.
			//print ($response);				
			// END GCM
			
		}
		
		//Encrypt the plain text
		//
		//Param: password as plain text
		//Return: Hash code
		function generateHash($plainText) {
			$salt = $this->getSalt();
			$hash = $salt . sha1($salt . $plainText);
			return $hash;
		}

		//Generate random token
		//
		//Return: random token
		function generateValidationToken() {
			$token = substr(uniqid ($this->getUsername(), true), -5);
			return $token;
		}

		//Send token to user's e-mail
		//Configuration of e-mail can be done in includes.php
		function sendEmailToken() {

			$mail = new PHPMailer();
			$mail->IsSMTP();
			$mail->From = 'no-reply@dangertracker.com';
			$email = $this->getEmail();
			$mail->AddAddress($email);
			$mail->Subject = 'Dangertracker Account creation and validation';
			
			$username = $this->getUsername();
			$token = $this->getValid();
			$body = "Please validate your account by clicking on the following link: <br /> 
					http://" . $_SERVER['HTTP_HOST'] . DIR . "/validate.php?user=" . $username . "&token=" . $token . "<br />
					Or using this the token: " . $token;
			$mail->Body = $body;
			
			$mail->Send();
		}

		//Send re-validation token to user's e-mail
		//Configuration of e-mail can be done in includes.php		
		function sendEmailNewToken() {

			$mail = new PHPMailer();
			$mail->IsSMTP();
			$mail->From = 'no-reply@dangertracker.com';
			$email = $this->getEmail();
			$mail->AddAddress($email);
			$mail->Subject = 'Dangertracker E-mail Changed and Account Re-validation.';
			
			$username = $this->getUsername();
			$token = $this->getValid();
			$body = "You have changed your e-mail address. <br /> Please re-validate your account by clicking on the following link: <br /> 
					http://" . $_SERVER['HTTP_HOST'] . DIR . "/validate.php?user=" . $username . "&token=" . $token . "<br />
					Or using this the token: " . $token;
			$mail->Body = $body;
			
			$mail->Send();
		}		

		//Send change e-mail token to user's e-mail given the token
		//Configuration of e-mail can be done in includes.php		
		//
		//Param: Change e-mail token
		function sendEmailChangeToken($token) {

			$mail = new PHPMailer();
			$mail->IsSMTP();
			$mail->From = 'no-reply@dangertracker.com';
			$email = $this->getEmail();
			$mail->AddAddress($email);
			$mail->Subject = 'Dangertracker E-mail Change Confirmation.';
			
			$username = $this->getUsername();

			$body = "You are trying to change your e-mail address. <br /> Please approve this change by clicking on the following link: <br /> 
					http://" . $_SERVER['HTTP_HOST'] . DIR . "/validate_email.php?user=" . $username . "&token=" . $token . "<br />
					Or using this the token: " . $token . "<br />
					If this was a mistake, please log in to your account and cancel it. Alternatively, you can send us an e-mail.";
			$mail->Body = $body;
			
			$mail->Send();
		}		

		//Check if the user has been validated
		//
		//Return: true or false
		function isValid() {
			$db = Database::get();
			$id = 0;
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_id = ? AND user_valid = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				$token = 'true';
				
				$stmt->bind_param("ss", $user_id, $token);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if (intval($id) !== 0) {
				return true;
			}
			return false;
		}
		
		//Find the salt of the user in the database given the ID
		//
		//Param: user id
		//Return: salt
		static function findSalt($id) {
			$password = null;
			$db = Database::get();
			$query = "SELECT user_password FROM " . USER_TABLE . "
					  WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($password);
				$stmt->fetch() or $password = null;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			$salt = "";
			//Checking purposes when password is null
			if ($password === null) {
			} else {
				$salt = substr($password, 0, SALT_LENGTH);
			}

			return $salt;
		}		
		
		//Compare the username and password with the database
		//Used for logins
		//
		//Param: username, password
		//Return: id or 0
		static function compare($username, $password) {
			$db = Database::get();

			$id = 0;
			$check_id = self::findID($username);
			$salt = self::findSalt($check_id);
			$password = $salt . sha1($salt . $password);
		
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_username = ? AND user_password = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("ss", $username, $password);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			
			return intval($id);
		}

		//Compare the username and token with the database
		//Used for validation
		//
		//Param: username, token
		//Return: true or false
		static function validate($username, $token) {
			$db = Database::get();
			$id = 0;
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_username = ? AND user_valid = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("ss", $username, $token);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if (intval($id) !== 0) {
				return self::changeToken($id, 'true');
			}
			return false;
		}

		//Find user id given the e-mail
		//
		//Param: e-mail
		//Return: id or 0
		static function findIDWithEmail($email) {
			$id = 0;
			$db = Database::get();
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_email = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("s", $email);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return intval($id);
		}	

		//Change the value of the token given the user id and value
		//
		//Param: user id, value (random token or 'true')
		//Return: true or false	
		static function changeToken($id, $val) {
			$db = Database::get();
			$query = "UPDATE " . USER_TABLE . " 
				SET user_valid = ? WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				
				$stmt->bind_param("sd", $val, $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();
				return true;
			}
			return false;
		}	

		//Check validation of user given the user id
		//
		//Param: user id
		//Return: true or false			
		static function checkValid($id) {
			$db = Database::get();
			$return_id = 0;
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_id = ? AND user_valid = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$token = 'true';
				$stmt->bind_param("ds", $id, $token);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($return_id);
				$stmt->fetch() or $return_id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if (intval($return_id) !== 0) {
				return true;
			}
			return false;
		}
		
		//Find the user id of the user given the username
		//
		//Param: username
		//Return: user id
		static function findID($username) {
			$id = 0;
			$db = Database::get();
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_username = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("s", $username);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return intval($id);
		}		
	
		//Find the username of the user given the user id
		//
		//Param: user id
		//Return: username	
		static function findUsername($id) {
			$db = Database::get();
			$username = null;
			
			$query = "SELECT user_username FROM " . USER_TABLE . "
					  WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("s", $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($username);
				$stmt->fetch() or $username = null;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return $username;
		}
		
		//Find the name of the user given the user id
		//Format as 'Firstname Lastname'
		//
		//Param: user id
		//Return: name
		static function findName($id) {
			$db = Database::get();
			$name = null;
			$query = "SELECT user_firstname, user_lastname FROM " . USER_TABLE . "
					  WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$result = $stmt->get_result();
				$user_row = null;
				if ($row = $result->fetch_assoc()) {
					$user_row = $row;
				}
				$name = $user_row['user_firstname'] . " " . $user_row['user_lastname'];
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return $name;
		}
		
		//Find the role of the user given the user id
		//
		//Param: user id
		//Return: role
		static function findRole($id) {
			$db = Database::get();
			$role = null;
			$query = "SELECT user_role FROM " . USER_TABLE . "
					  WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("s", $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($role);
				$stmt->fetch() or $role = null;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return $role;
		}		

		//Get the list of notification of the User given the page and show
		//Show is the number of notification to display
		//Page is the page of notification, divided by show
		//
		//Param: page, show
		//Return: list of notification
		function getNotificationList($page = 1, $show = 10) {
			$start = 0 + ($page-1) * $show;
			$user_id = $this->getUserID();
			$notification_list = Notification::getNotificationList($user_id, $start, $show);
			return $notification_list;
		}		
		
		//Create User object given the ID by taking information from the database
		//Information taken from the database: username, email, first name, last name,
		//	gender, address, contact, date of birth (dob), role, time, valid token
		//
		//Param: user id
		//Return: User object		
		static function createUser($id) {
			$db = Database::get();
			$query = "SELECT * FROM " . USER_TABLE . "
					  WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$result = $stmt->get_result();
				$user_row = null;
				if ($row = $result->fetch_assoc()) {
					$user_row = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			
			$user = null;
			if ($user_row !== null) {
				$user_username = $user_row['user_username'];
				$user_email = $user_row['user_email'];

				$user_firstname = $user_row['user_firstname'];
				$user_lastname = $user_row['user_lastname'];
				$user_gender = $user_row['user_gender'];
				
				//Decode start
				$user_address = base64_decode($user_row['user_address']);
				$user_contact = base64_decode($user_row['user_contact']);
				$user_dob = base64_decode($user_row['user_dob']);
				//Decode end
				
				$user_role = $user_row['user_role'];
				$user_time = $user_row['created_at'];
				
				$user_valid = $user_row['user_valid'];

				$user = new User($user_username, null, $user_email, $user_firstname, $user_lastname, $user_gender, 
									$user_address, $user_contact, $user_dob, $user_role, $user_time);
				$user->setUserID($id);
				$user->setValid($user_valid);
				}				
			return $user;
		}
		
		//Check if the username has already exist in the database
		//Used for validations
		//
		//Param: username
		//Return: true or false
		static function checkUsername($username) {
			$id = 0;
			$db = Database::get();
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_username = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("s", $username);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if ($id !== 0) {
				return true;
			}		
			return false;
		}		

		//Check if the e-mail has already exist in the database
		//Used for validations
		//
		//Param: e-mail
		//Return: true or false		
		static function checkEmail($email) {
			$id = 0;
			$db = Database::get();
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_email = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("s", $email);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if ($id !== 0) {
				return true;
			}		
			return false;
		}

		//Check if the username and e-mail belong to the same user
		//
		//Param: username, e-mail
		//Return: true or false				
		static function checkUsernameAndEmail($username, $email) {
			$id = 0;
			$db = Database::get();
			$query = "SELECT user_id FROM " . USER_TABLE . "
					  WHERE user_username = ? AND user_email = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("ss", $username, $email);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			if ($id !== 0) {
				return true;
			}		
			return false;
		}

		//Reset the password given the username or e-mail
		//Send a random generated password to the e-mail
		//
		//Param: username, e-mail
		//Return: true or false			
		static function resetPassword($username, $email) {
			$user_id = self::findID($username);
			$salt = self::findSalt($user_id);
			$new_password = substr(md5(uniqid(rand(), true)), 0, 8);
			
			$hash_password = $salt . sha1($salt . $new_password);
			
			$db = Database::get();
			$query = "UPDATE " . USER_TABLE . " 
				SET user_password = ?
				WHERE user_username = ? AND user_email = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				
				$stmt->bind_param("sss", $hash_password, $username, $email);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->close();

				//Send e-mail
				//Configuration of e-mail is includes.php
				$mail = new PHPMailer();
				$mail->IsSMTP();
				$mail->From = 'no-reply@dangertracker.com';
				$mail->AddAddress($email);
				$mail->Subject = 'Reset Password';
				
				$body = "Username: " . $username . "<br />
						Your new password is <b>" . $new_password  . "</b> <br />
						http://" . $_SERVER['HTTP_HOST'] . DIR;
				$mail->Body = $body;
				
				$mail->Send();
				
				return true;
			}
			
			return false;

		}
	}
?>